<html lang="zh"><head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>2048游戏 - Vue.js版</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <!-- 添加中国风字体 -->
    <link href="https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&family=ZCOOL+XiaoWei&display=swap" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#faf8ef',
                        secondary: '#bbada0',
                        cellEmpty: '#cdc1b4',
                        cell2: '#eee4da',
                        cell4: '#ede0c8',
                        cell8: '#f2b179',
                        cell16: '#f59563',
                        cell32: '#f67c5f',
                        cell64: '#f65e3b',
                        cell128: '#edcf72',
                        cell256: '#edcc61',
                        cell512: '#edc850',
                        cell1024: '#edc53f',
                        cell2048: '#edc22e',
                        textDark: '#776e65',
                        textLight: '#f9f6f2',
                        accent: '#8B0000', // 中国红
                        gold: '#D4AF37', // 金色
                        ink: '#1A1A1A', // 墨色
                    },
                    fontFamily: {
                        game: ['"ZCOOL XiaoWei"', '"Clear Sans"', 'Helvetica Neue', 'Arial', 'sans-serif'],
                        chinese: ['"Ma Shan Zheng"', 'cursive'] // 中国风字体
                    }
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .tile-appear {
                animation: tileAppear 0.3s ease-out forwards;
            }
            .tile-merge {
                animation: tileMerge 0.2s ease-in-out forwards;
            }
            .tile-move {
                transition: transform 0.15s ease-out;
            }
            @keyframes tileAppear {
                0% { transform: scale(0.8); opacity: 0.6; }
                100% { transform: scale(1); opacity: 1; }
            }
            @keyframes tileMerge {
                0% { transform: scale(1); }
                50% { transform: scale(1.2); }
                100% { transform: scale(1); }
            }
            .text-shadow {
                text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
            }
            .text-shadow-lg {
                text-shadow: 3px 3px 6px rgba(0, 0, 0, 0.5);
            }
            .bg-blur {
                backdrop-filter: blur(5px);
            }
            .chinese-number {
                font-family: 'Ma Shan Zheng', cursive;
                text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
            }
            .cell-border {
                position: relative;
            }
            .cell-border::before {
                content: "";
                position: absolute;
                inset: 0;
                border: 2px solid rgba(212, 175, 55, 0.3);
                border-radius: inherit;
                pointer-events: none;
            }
            .game-container {
                max-height: 90vh;
                overflow-y: auto;
            }
        }
    </style>
</head>
<body class="font-game text-textDark min-h-screen flex flex-col items-center justify-center p-2 overflow-hidden relative">
    <!-- 长城背景图 -->
    <div class="absolute inset-0 z-0">
        <img src="https://picsum.photos/id/1036/1920/1080" alt="宏伟的长城风景" class="w-full h-full object-cover">
        <div class="absolute inset-0 bg-black/30"></div>
    </div>

    <div id="app" class="max-w-md w-full mx-auto relative z-10 bg-primary/90 rounded-xl p-4 shadow-2xl game-container">
        <header class="flex flex-col md:flex-row justify-between items-start md:items-center mb-4">
            <div>
                <!-- 中国风字体 -->
                <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-chinese font-bold mb-2 text-accent text-shadow-lg">2048小游戏</h1>
                <p class="text-xs md:text-sm mb-3">合并数字，得到 <strong>2048 方块！</strong></p>
            </div>
            <div class="flex gap-2 mb-3 md:mb-0">
                <div class="bg-secondary rounded-lg p-2 text-center min-w-[70px]">
                    <div class="text-xs uppercase font-bold text-primary/80">分数</div>
                    <div class="text-lg font-bold text-white">{{ score }}</div>
                </div>
                <div class="bg-secondary rounded-lg p-2 text-center min-w-[70px]">
                    <div class="text-xs uppercase font-bold text-primary/80">最高分</div>
                    <div class="text-lg font-bold text-white">{{ bestScore }}</div>
                </div>
            </div>
        </header>

        <button @click="newGame" class="bg-cell8 hover:bg-cell16 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-300 mb-4 w-full">
            <i class="fa fa-refresh mr-2"></i>新游戏
        </button>

        <div class="relative">
            <div v-if="showMessage" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
                <div class="bg-primary rounded-lg p-6 text-center max-w-xs">
                    <h2 class="text-xl font-bold mb-3">{{ messageText }}</h2>
                    <button @click="hideMessage" class="bg-cell8 hover:bg-cell16 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-300">
                        继续
                    </button>
                </div>
            </div>

            <div class="bg-secondary rounded-lg p-2 mb-4">
                <div class="grid grid-cols-4 gap-2 relative" style="height: 0; padding-bottom: 100%;">
                    <!-- 背景单元格 -->
                    <div v-for="(cell, index) in 16" :key="index" class="bg-cellEmpty rounded-md aspect-square cell-border"></div>
                    
                    <!-- 数字方块 -->
                    <div v-for="(tile, index) in tiles" :key="index" :class="getTileClass(tile)" :style="{
                            width: 'calc(25% - 6px)',
                            height: 'calc(25% - 6px)',
                            left: `calc(${tile.x * 25}% + ${tile.x * 2}px + 3px)`,
                            top: `calc(${tile.y * 25}% + ${tile.y * 2}px + 3px)`
                        }">
                        <span class="chinese-number">{{ tile.value }}</span>
                    </div>
                </div>
            </div>

            <div class="text-xs mb-3">
                <p class="mb-1"><strong>玩法：</strong> 使用 <span class="font-bold">方向键</span> 移动方块。当两个相同数字的方块相遇时，它们将 <span class="font-bold">合并为一个！</span></p>
                <p>你也可以使用 <span class="font-bold">WASD键</span> 或在移动设备上 <span class="font-bold">滑动</span>。</p>
            </div>
        </div>
    </div>

    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    grid: Array(4).fill().map(() => Array(4).fill(0)),
                    score: 0,
                    bestScore: localStorage.getItem('2048-best-score') || 0,
                    gameOver: false,
                    gameWon: false,
                    showMessage: false,
                    messageText: '',
                    canMove: true,
                    mergedCells: [],
                    newCells: []
                }
            },
            computed: {
                tiles() {
                    const tiles = [];
                    for (let y = 0; y < 4; y++) {
                        for (let x = 0; x < 4; x++) {
                            if (this.grid[y][x] !== 0) {
                                tiles.push({
                                    x,
                                    y,
                                    value: this.grid[y][x],
                                    isNew: this.newCells.some(cell => cell.x === x && cell.y === y),
                                    isMerged: this.mergedCells.some(cell => cell.x === x && cell.y === y)
                                });
                            }
                        }
                    }
                    return tiles;
                }
            },
            created() {
                this.initGame();
                this.setupEventListeners();
            },
            methods: {
                initGame() {
                    this.grid = Array(4).fill().map(() => Array(4).fill(0));
                    this.score = 0;
                    this.gameOver = false;
                    this.gameWon = false;
                    this.canMove = true;
                    this.mergedCells = [];
                    this.newCells = [];
                    
                    this.updateBestScore();
                    this.generateRandomTile();
                    this.generateRandomTile();
                },
                
                setupEventListeners() {
                    document.addEventListener('keydown', this.handleKeydown);
                    
                    // 触摸事件处理
                    let touchStartX = 0;
                    let touchStartY = 0;
                    
                    document.addEventListener('touchstart', (e) => {
                        touchStartX = e.touches[0].clientX;
                        touchStartY = e.touches[0].clientY;
                    }, false);
                    
                    document.addEventListener('touchend', (e) => {
                        if (!this.canMove) return;
                        
                        const touchEndX = e.changedTouches[0].clientX;
                        const touchEndY = e.changedTouches[0].clientY;
                        
                        const dx = touchEndX - touchStartX;
                        const dy = touchEndY - touchStartY;
                        
                        // 根据距离确定滑动方向
                        if (Math.abs(dx) > Math.abs(dy)) {
                            // 水平滑动
                            if (dx > 30) {
                                this.moveRight();
                            } else if (dx < -30) {
                                this.moveLeft();
                            }
                        } else {
                            // 垂直滑动
                            if (dy > 30) {
                                this.moveDown();
                            } else if (dy < -30) {
                                this.moveUp();
                            }
                        }
                    }, false);
                },
                
                generateRandomTile() {
                    if (!this.hasEmptyCell()) return;
                    
                    let emptyCells = [];
                    for (let y = 0; y < 4; y++) {
                        for (let x = 0; x < 4; x++) {
                            if (this.grid[y][x] === 0) {
                                emptyCells.push({ x, y });
                            }
                        }
                    }
                    
                    const { x, y } = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    const value = Math.random() < 0.9 ? 2 : 4;
                    this.grid[y][x] = value;
                    this.newCells.push({x, y});
                },
                
                hasEmptyCell() {
                    for (let y = 0; y < 4; y++) {
                        for (let x = 0; x < 4; x++) {
                            if (this.grid[y][x] === 0) {
                                return true;
                            }
                        }
                    }
                    return false;
                },
                
                getTileClass(tile) {
                    let baseClass = 'absolute rounded-md flex items-center justify-center font-bold';
                    
                    // 添加适当的动画类
                    if (tile.isNew) {
                        baseClass += ' tile-appear';
                    } else if (tile.isMerged) {
                        baseClass += ' tile-merge';
                    } else {
                        baseClass += ' tile-move';
                    }
                    
                    // 添加颜色类
                    const colorClasses = {
                        2: 'bg-cell2 text-textDark text-[clamp(1.2rem,4vw,1.8rem)]',
                        4: 'bg-cell4 text-textDark text-[clamp(1.2rem,4vw,1.8rem)]',
                        8: 'bg-cell8 text-textLight text-[clamp(1.2rem,4vw,1.8rem)]',
                        16: 'bg-cell16 text-textLight text-[clamp(1.2rem,4vw,1.8rem)]',
                        32: 'bg-cell32 text-textLight text-[clamp(1.2rem,4vw,1.8rem)]',
                        64: 'bg-cell64 text-textLight text-[clamp(1.2rem,4vw,1.8rem)]',
                        128: 'bg-cell128 text-textLight text-[clamp(1rem,3vw,1.5rem)]',
                        256: 'bg-cell256 text-textLight text-[clamp(1rem,3vw,1.5rem)]',
                        512: 'bg-cell512 text-textLight text-[clamp(1rem,3vw,1.5rem)]',
                        1024: 'bg-cell1024 text-textLight text-[clamp(0.9rem,2.5vw,1.3rem)]',
                        2048: 'bg-cell2048 text-textLight text-[clamp(0.9rem,2.5vw,1.3rem)]'
                    };
                    
                    return `${baseClass} ${colorClasses[tile.value] || 'bg-black text-white text-[clamp(0.9rem,2.5vw,1.3rem)]'}`;
                },
                
                updateBestScore() {
                    if (this.score > this.bestScore) {
                        this.bestScore = this.score;
                        localStorage.setItem('2048-best-score', this.bestScore);
                    }
                },
                
                handleKeydown(e) {
                    if (!this.canMove) return;
                    
                    this.mergedCells = [];
                    
                    switch (e.key) {
                        case 'ArrowUp':
                        case 'w':
                        case 'W':
                            this.moveUp();
                            break;
                        case 'ArrowDown':
                        case 's':
                        case 'S':
                            this.moveDown();
                            break;
                        case 'ArrowLeft':
                        case 'a':
                        case 'A':
                            this.moveLeft();
                            break;
                        case 'ArrowRight':
                        case 'd':
                        case 'D':
                            this.moveRight();
                            break;
                        default:
                            return; // 忽略其他键
                    }
                },
                
                moveUp() {
                    let moved = false;
                    const previousGrid = JSON.stringify(this.grid);
                    
                    for (let x = 0; x < 4; x++) {
                        for (let y = 1; y < 4; y++) {
                            if (this.grid[y][x] !== 0) {
                                let newY = y;
                                
                                // 尽可能向上移动方块
                                while (newY > 0 && this.grid[newY - 1][x] === 0) {
                                    this.grid[newY - 1][x] = this.grid[newY][x];
                                    this.grid[newY][x] = 0;
                                    newY--;
                                    moved = true;
                                }
                                
                                // 如果可能，与上方方块合并
                                if (newY > 0 && this.grid[newY - 1][x] === this.grid[newY][x]) {
                                    this.grid[newY - 1][x] *= 2;
                                    this.score += this.grid[newY - 1][x];
                                    this.grid[newY][x] = 0;
                                    this.mergedCells.push({x, y: newY - 1});
                                    moved = true;
                                }
                            }
                        }
                    }
                    
                    if (moved) {
                        this.afterMove();
                    }
                    
                    return moved;
                },
                
                moveDown() {
                    let moved = false;
                    const previousGrid = JSON.stringify(this.grid);
                    
                    for (let x = 0; x < 4; x++) {
                        for (let y = 2; y >= 0; y--) {
                            if (this.grid[y][x] !== 0) {
                                let newY = y;
                                
                                // 尽可能向下移动方块
                                while (newY < 3 && this.grid[newY + 1][x] === 0) {
                                    this.grid[newY + 1][x] = this.grid[newY][x];
                                    this.grid[newY][x] = 0;
                                    newY++;
                                    moved = true;
                                }
                                
                                // 如果可能，与下方方块合并
                                if (newY < 3 && this.grid[newY + 1][x] === this.grid[newY][x]) {
                                    this.grid[newY + 1][x] *= 2;
                                    this.score += this.grid[newY + 1][x];
                                    this.grid[newY][x] = 0;
                                    this.mergedCells.push({x, y: newY + 1});
                                    moved = true;
                                }
                            }
                        }
                    }
                    
                    if (moved) {
                        this.afterMove();
                    }
                    
                    return moved;
                },
                
                moveLeft() {
                    let moved = false;
                    const previousGrid = JSON.stringify(this.grid);
                    
                    for (let y = 0; y < 4; y++) {
                        for (let x = 1; x < 4; x++) {
                            if (this.grid[y][x] !== 0) {
                                let newX = x;
                                
                                // 尽可能向左移动方块
                                while (newX > 0 && this.grid[y][newX - 1] === 0) {
                                    this.grid[y][newX - 1] = this.grid[y][newX];
                                    this.grid[y][newX] = 0;
                                    newX--;
                                    moved = true;
                                }
                                
                                // 如果可能，与左方方块合并
                                if (newX > 0 && this.grid[y][newX - 1] === this.grid[y][newX]) {
                                    this.grid[y][newX - 1] *= 2;
                                    this.score += this.grid[y][newX - 1];
                                    this.grid[y][newX] = 0;
                                    this.mergedCells.push({x: newX - 1, y});
                                    moved = true;
                                }
                            }
                        }
                    }
                    
                    if (moved) {
                        this.afterMove();
                    }
                    
                    return moved;
                },
                
                moveRight() {
                    let moved = false;
                    const previousGrid = JSON.stringify(this.grid);
                    
                    for (let y = 0; y < 4; y++) {
                        for (let x = 2; x >= 0; x--) {
                            if (this.grid[y][x] !== 0) {
                                let newX = x;
                                
                                // 尽可能向右移动方块
                                while (newX < 3 && this.grid[y][newX + 1] === 0) {
                                    this.grid[y][newX + 1] = this.grid[y][newX];
                                    this.grid[y][newX] = 0;
                                    newX++;
                                    moved = true;
                                }
                                
                                // 如果可能，与右方方块合并
                                if (newX < 3 && this.grid[y][newX + 1] === this.grid[y][newX]) {
                                    this.grid[y][newX + 1] *= 2;
                                    this.score += this.grid[y][newX + 1];
                                    this.grid[y][newX] = 0;
                                    this.mergedCells.push({x: newX + 1, y});
                                    moved = true;
                                }
                            }
                        }
                    }
                    
                    if (moved) {
                        this.afterMove();
                    }
                    
                    return moved;
                },
                
                afterMove() {
                    this.newCells = [];
                    
                    // 等待一小段时间让动画开始
                    setTimeout(() => {
                        this.generateRandomTile();
                        
                        // 重置动画标记
                        setTimeout(() => {
                            this.mergedCells = [];
                            this.newCells = [];
                            this.checkGameState();
                        }, 150);
                    }, 50);
                },
                
                checkGameState() {
                    this.updateBestScore();
                    
                    // 检查获胜条件
                    if (!this.gameWon) {
                        for (let y = 0; y < 4; y++) {
                            for (let x = 0; x < 4; x++) {
                                if (this.grid[y][x] >= 2048) {
                                    this.gameWon = true;
                                    this.showMessage = true;
                                    this.messageText = '你赢了！';
                                    return;
                                }
                            }
                        }
                    }
                    
                    // 检查游戏结束条件
                    if (!this.hasEmptyCell()) {
                        // 检查是否还有移动可能
                        for (let y = 0; y < 4; y++) {
                            for (let x = 0; x < 4; x++) {
                                // 检查右侧
                                if (x < 3 && this.grid[y][x] === this.grid[y][x + 1]) {
                                    return;
                                }
                                // 检查下方
                                if (y < 3 && this.grid[y][x] === this.grid[y + 1][x]) {
                                    return;
                                }
                            }
                        }
                        
                        // 没有移动可能
                        this.gameOver = true;
                        this.showMessage = true;
                        this.messageText = '游戏结束！';
                    }
                },
                
                newGame() {
                    this.initGame();
                    this.showMessage = false;
                },
                
                hideMessage() {
                    this.showMessage = false;
                    this.canMove = true;
                }
            }
        });
    </script>

</body></html>    